const app = Vue.createApp({
    data() {
        return {
            num: 36,     // 生成多少个格子
            n: '2',        // 生成几层的游戏
            resData: [], // 存储下方结果区的数据
            text: '',    // 提示信息
            dialogVisible: false, // 是否显示弹窗
            res: true,   // 是否结束
            itemData: [], // 所有的游戏数据
            imagePre: "./images/img/",
            seconds: 0,  // 计时
            timer: null, // 定时器
            time: "00:00:00",     // 用时
            points: 0,   // 分数
            point: 100,   // 基础得分
            difficulty_factor: "中等",    // 难度等级
            result: false, // 游戏结果
            total: 0, // 生成的总共格子数量
            submitState: false, // 是否提交
            started: false,     // 是否开始游戏
            show: false,        // 是否显示游戏区
            options: [
                {difficulty_factor: "简单",n:1 ,label: '天堂模式'},
                {difficulty_factor: "中等",n:2 ,label: '人间模式'},
                {difficulty_factor: "困难",n:3 ,label: '地狱模式'},
            ],
        }
    },
    watch: {
        resData: {
            handler: function (val, oldVal) {
                if (this.getValidNum() <= 0 && this.resData.length == 0) {
                    this.dialogVisible = true
                    this.text = "恭喜，你赢了！用时：" + this.time
                    this.result = true
                    this.clearTimer()
                }
                setTimeout(() => {
                    if (this.resData.length >= 7) {
                        this.dialogVisible = true;
                        this.text = "对不起，你输了！"
                        this.result = false
                        sessionStorage.clear()
                    }
                }, 300)
            },
            deep: true
        },
    },
    methods: {
        // 选择模式
        choose_style() {
            sessionStorage.clear()
            this.started = true
            this.clearTimer()
            this.time = "00:00:00"
            this.seconds = 0
            this.itemData = []
            this.getCode()
            this.resData = []
            this.points = 0
            this.dialogVisible = false
            },


        // 开始游戏
        begin() {
            this.show = true
            this.started = true
            this.checkHistory()
        },
        // 重新开始
        again() {
            // 清理缓存
            sessionStorage.clear()
            this.started = true
            this.clearTimer()
            this.time = "00:00:00"
            this.seconds = 0
            this.itemData = []
            this.getCode()
            this.resData = []
            this.points = 0
            this.dialogVisible = false
        },
        // 继续游戏 从存储中获取数据
        continue() {
            this.timer = sessionStorage.getItem('timer')
            this.clearTimer()
            // 获取本地存储的数据
            this.resData = JSON.parse(sessionStorage.getItem('resData'))
            this.points = parseInt(sessionStorage.getItem('points'))
            this.seconds = parseInt(sessionStorage.getItem('seconds'))
            this.itemData = JSON.parse(sessionStorage.getItem('itemData'))
            this.time = sessionStorage.getItem('time')
            // 继续开始计时
            this.countTime()
            this.total = parseInt(sessionStorage.getItem('total'))
        },
        // 暂停/继续游戏 存储游戏数据到session中
        to_paused() {
            if (this.started) {
                this.started = false
                this.clearTimer()
                sessionStorage.removeItem("seconds")
                sessionStorage.removeItem("time")
                sessionStorage.removeItem("timer")
                sessionStorage.removeItem("resData")
                sessionStorage.removeItem("points")
                sessionStorage.removeItem("point")
                sessionStorage.removeItem("total")
                sessionStorage.removeItem("itemData")
                sessionStorage.setItem("seconds", this.seconds)
                sessionStorage.setItem("time", this.time)
                sessionStorage.setItem("timer", this.timer)
                sessionStorage.setItem("resData", JSON.stringify(this.resData))
                sessionStorage.setItem("points", this.points)
                sessionStorage.setItem("point", this.point)
                sessionStorage.setItem("total", this.total)
                sessionStorage.setItem("itemData", JSON.stringify(this.itemData))
            } else {
                this.started = true
                this.continue()
            }
        },
        // 退出游戏
        quit() {
            this.show = false
            sessionStorage.clear()
            // 弹出提示框退出成功
            window.ElementPlus.ElMessage({
                message: '已结束游戏',
                type: 'success'
            });
        },
        // 获取数据
        getCode() {
            // 随机生成随机数
            let numbers = this.rand(this.num / 3 - this.random(3))
            // 如果数组长度小于要生成的数量，填充剩余位置为-1
            // 有效牌组数量
            this.total += numbers.length
            if (numbers.length < this.num) {
                let len = numbers.length;
                for (let i = 0; i < this.num - len; i++) {
                    numbers.push(-1)
                }
            }
            // 随机打乱数组元素顺序  打乱三次
            numbers = this.shuffleArray(numbers, 3)
            // 当前层的行数
            let row = Math.ceil(Math.sqrt(this.num))
            let oldRow = row
            let layer = this.n
            // 初始化每一个格子的位置
            while (row > 0 && layer-- > 0) {
                let r = 0
                for (let i = 0; i < numbers.length; i++) {
                    // 通过定位控制每个元素的位置
                    let style = "position: absolute;"
                    let num = numbers[i]
                    // 每一行的第一个
                    if (i % row == 0) {
                        style += "top: " + (i / row * 60 + 10) + "px;"
                    } else { // 其余情况
                        style += "left: " + ((i % row + r) * 60 + 10) + "px;top:" + (Math.floor(i / row) * 60 + 10) +
                            "px;"
                    }
                    // 不是第一层的情况
                    if (row != oldRow) {
                        style += "z-index:" + (1 + oldRow - row) + ";top:" +
                            ((oldRow - row) * 30 + Math.floor(i / row) * 60) + "px;left:" +
                            ((oldRow - row) * 30 + (i % row + r) * 60) + "px;"
                    }

                    // 生成字母
                    let code = num == -1 ? 0 : num + 65;
                    code = Math.max(66, Math.min(75, code));
                    this.itemData.push({
                        num: num,
                        code: String.fromCharCode(code),
                        style: style,
                        id: "sm" + (oldRow - row) + '-' + (Math.floor(i / row)) + '-' + (i % row),
                        cls: num == -1 ? "display" : "" // 如果是-1 则不显示
                    })
                }
                row--
                numbers = this.rand(row * row / 3 - this.random(3))
                this.total += numbers.length
                if (numbers.length < row * row) {
                    let len = numbers.length;
                    for (let i = 0; i < (row * row) - len; i++) {
                        numbers.push(-1)
                    }
                }
                numbers = this.shuffleArray(numbers, 3)
            }
            this.countTime()
        },
        // 点击元素，放到结果区
        check(code, index, id) {
            if (this.started) {
                const _this = $("#" + id)
                const cssList = _this.attr('class')
                if (!cssList.includes('disabled')) { // 判断是否不可点击
                    if (this.resData.length < 7) {   // 如果结果区的数据小于7个，就添加
                        this.resData.push(code)
                        this.itemData.splice(index, 1)
                        if (this.isThree(code)) {
                            setTimeout(() => {
                                this.delCode(code)
                                this.points += this.point
                            }, 250);
                        }
                    }
                }
            } else {
                window.ElementPlus.ElMessage({
                    message: '请先开始游戏',
                    type: 'warning'
                });
            }

        },
        // 初始化table的宽高
        initTable() {
            $('.table').width(Math.ceil(Math.sqrt(this.num)) * 60 - 5)
            $('.table').height(Math.ceil(Math.sqrt(this.num)) * 60 - 10)
        },
        // 判断是否有历史记录未完成
        checkHistory() {
            // 获取本地存储的数据
            const itemData = JSON.parse(sessionStorage.getItem('itemData'))
            if (itemData) {
                window.ElementPlus.ElMessageBox.confirm('存在未完成的对局，是否继续?', '提示', {
                    confirmButtonText: '继续',
                    cancelButtonText: '重新开始',
                    type: 'warning',
                }).then(() => {
                    // 用户点击了继续按钮的回调函数
                    this.continue()
                }).catch(() => {
                    // 用户点击了重新开始按钮的回调函数
                    this.again()
                });
            } else {
                this.again()
            }
        },
        // 添加遮挡
        mask() {
            let oldRow = Math.ceil(Math.sqrt(this.num))
            for (let i = this.n - 1; i >= 0; i--) {
                for (let j = 0; j < oldRow - i; j++) {
                    for (let n = 0; n < oldRow - i; n++) {
                        const item = $('#sm' + i + '-' + j + '-' + n)
                        if (item.length) {
                            // 给当前元素的压住的元素添加遮罩
                            let back1 = $('#sm' + (i - 1) + '-' + j + '-' + n)
                            let back2 = $('#sm' + (i - 1) + '-' + j + '-' + (n + 1))
                            let back3 = $('#sm' + (i - 1) + '-' + (j + 1) + '-' + n)
                            let back4 = $('#sm' + (i - 1) + '-' + (j + 1) + '-' + (n + 1))
                            back1.addClass('disabled')
                            back2.addClass('disabled')
                            back3.addClass('disabled')
                            back4.addClass('disabled')
                        }
                    }
                }
            }
        },
        // 删除遮挡
        removemask() {
            let oldRow = Math.ceil(Math.sqrt(this.num))
            for (let i = this.n - 1; i >= 0; i--) {
                for (let j = 0; j < oldRow - i; j++) {
                    for (let n = 0; n < oldRow - i; n++) {
                        // 获取到当前的元素
                        const item = $('#sm' + i + '-' + j + '-' + n)
                        // 获取当前元素的的四个角的元素
                        let back1 = $('#sm' + (i + 1) + '-' + j + '-' + n)
                        let back2 = $('#sm' + (i + 1) + '-' + j + '-' + (n - 1))
                        let back3 = $('#sm' + (i + 1) + '-' + (j - 1) + '-' + n)
                        let back4 = $('#sm' + (i + 1) + '-' + (j - 1) + '-' + (n - 1))
                        const cls = 'display'
                        // 如果四个交叉点都没有元素，就删除遮罩或者交叉点的元素是不显示的
                        if ((!back1.length || this.hasClass(back1, cls))
                            && (!back2.length || this.hasClass(back2, cls))
                            && (!back3.length || this.hasClass(back3, cls))
                            && (!back4.length || this.hasClass(back4, cls))) {
                            item.removeClass('disabled')
                        }
                    }
                }
            }
        },
        // 存储数据 记录对局结果
        submit() {
            const data = {
                username: this.username,
                points: this.points,
                seconds: this.seconds,
                endTime: new Date().toLocaleString(),
                difficultyFactor: this.n,
                total: this.total
            }
            fetch('http://localhost:8090/api/data', {
                method: 'post',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data)
            }).then(response => response.json())
                .then(data => {
                    if (data && data.affectedRows > 0) {
                        this.submitState = true
                    }
                })
                .catch(error => {
                    console.error(error);
                });
        },
        // 打开排行榜
        to_rank() {
            // 页面跳转
            window.location.href = './views/rank.html'
            setInterval(() => {
                this.getRank()
            }, 1000 * 10)
        },
        // ********我是分割线******
        // 下面是一些工具方法
        // 获取有效的格子数量
        getValidNum() {
            let num = 0
            this.itemData.forEach(item => {
                if (item.num !== -1) {
                    num++
                }
            })
            return num
        },
        // 计算游戏时长
        countTime() {
            this.timer = timerInterval = setInterval(() => {
                this.seconds++;
                this.time = this.formatTime(this.seconds);
            }, 1000); // 每秒执行一次
        },
        // 校验是否含有三个一样字母，
        isThree(code) {
            let count = 0;
            this.resData.forEach(w => {
                if (w == code) {
                    count++
                }
            })
            return count == 3
        },
        // 清除定时器
        clearTimer() {
            clearInterval(this.timer)
        },
        // 格式化时间
        formatTime(time) {
            let hours = Math.floor(time / 3600);
            let minutes = Math.floor((time % 3600) / 60);
            let seconds = time % 60;

            // 将时间补零到两位数
            let formattedHours = String(hours).padStart(2, "0");
            let formattedMinutes = String(minutes).padStart(2, "0");
            let formattedSeconds = String(seconds).padStart(2, "0");

            return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
        },
        // 删除相同字母
        delCode(code) {
            while (this.resData.indexOf(code) != -1) {
                this.resData.splice(this.resData.indexOf(code), 1)
            }
        },
        // 随机一个n以内的数
        random(n) {
            return Math.floor(Math.random() * n)
        },
        // 随机打乱数组元素
        shuffleArray(array, number) {
            for (let index = 0; index < number; index++) {
                for (let i = array.length - 1; i > 0; i--) {
                    const j = Math.floor(this.random(i + 1));
                    [array[i], array[j]] = [array[j], array[i]];
                }
            }
            return array;
        },
        // 是否含有某个类名
        hasClass(obj, cls) {
            return obj.attr('class').includes(cls);
        },
        // 获取num * 3 个随机数, 定义图片排列顺序
        rand(num) {
            let numbers = []
            for (let i = 1; i <= num; i++) {
                let rNum = Math.ceil(Math.random() * num)
                if (numbers.indexOf(rNum) == -1) {
                    numbers.push(rNum)
                    numbers.push(rNum)
                    numbers.push(rNum)
                } else {
                    i--
                }
            }
            return numbers
        },
    },
    // 页面挂载之前执行
    mounted() {
        switch (this.n) {
            case 1:
                this.difficulty_factor = "简单"
                break
            case 2:
                this.difficulty_factor = "中等"
                break
            case 3:
                this.difficulty_factor = "困难"
                break
            default:
                this.difficulty_factor = "简单"
        }
        this.initTable()
    },
    updated() {
        this.mask()
        this.removemask()
    },

})
app.use(ElementPlus);
app.mount("#view")